
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#include "AllocObject.h"
#include "DynamicCodeLoader.h"
#include "ExtendModule.h"


#define DEFAULT_MODULE_NUM	32

#ifdef WINCE
#define strdup _strdup
#endif

extern "C"
{

	static void FreeDCodeLoader(struct HT_entry *e)
	{
		if (e->k != LH_EMPTY)
		{
			OSFree(e->k);
			e->k = LH_EMPTY;
		}
		CDCodeLoader *cdl = (CDCodeLoader*)e->v;
		if (cdl)
		{
			delete cdl;
		}
	}

}


CExtendModule::CExtendModule()
{
	struct HT_table *ht = HT_kchar_table_new(DEFAULT_MODULE_NUM, "ExtendModule", &FreeDCodeLoader);
	m_moduleHashTable = (void*)ht;
}

CExtendModule::~CExtendModule()
{
	if (m_moduleHashTable)
	{
		HT_table_free((struct HT_table *)m_moduleHashTable);
	}
}

int CExtendModule::RegisterModule(char *path, char *moduleName, char **apilist, int apinum)
{
	if (!m_moduleHashTable)
	{
		return -1;
	}

	struct HT_entry* entry = HT_table_lookup_entry((struct HT_table*)m_moduleHashTable, moduleName);
	if (entry)
	{
		// This module already exists, delete it first
		HT_table_delete_entry((struct HT_table *)m_moduleHashTable, entry);
	}

	CDCodeLoader *cdl = new CDCodeLoader();

	if (cdl)
	{
		if (path[0] == '\\' && path[1] == '\\')
		{
			path++;
		}
		if (cdl->LoadModule(path, apilist, apinum))
		{
#if WIN32
			HT_table_insert((struct HT_table *)m_moduleHashTable, _strdup(moduleName), cdl);
#else
			HT_table_insert((struct HT_table *)m_moduleHashTable, strdup(moduleName), cdl);
#endif
		}
		else
		{
			delete cdl;
		}
	}
	else
	{
		return -2;
	}
	return 0;
}

int CExtendModule::ReleaseModule(char *moduleName)
{
	if (!m_moduleHashTable)
	{
		return 0;
	}

	struct HT_entry* entry = HT_table_lookup_entry((struct HT_table*)m_moduleHashTable, moduleName);
	if (entry)
	{
		HT_table_delete_entry((struct HT_table *)m_moduleHashTable, entry);
	}
	return 0;
}

void *CExtendModule::CallAPI(char *module, char* api, char *params)
{
	if (m_moduleHashTable)
	{
		struct HT_entry* entry = HT_table_lookup_entry((struct HT_table*)m_moduleHashTable, module);
		if (entry)
		{
			CDCodeLoader *cdl = (CDCodeLoader *)entry->v;
			return cdl->CallAPI(api, params);
		}
	}
	return NULL;
}

void CExtendModule::WndProc(unsigned int message, unsigned long wParam, unsigned long lParam)
{
	if (m_moduleHashTable)
	{
		struct HT_table* table = (struct HT_table*)m_moduleHashTable;
		struct HT_entry* entry;
		HT_foreach(table, entry)
		{
			if (entry)
			{
				CDCodeLoader *cdl = (CDCodeLoader *)entry->v;
				cdl->WndProc(message, wParam, lParam);
			}
		}
	}
}
